define(['jquery'], function ($) {


    function DatePicker(options) {

        var ele = $(this);
        var pos = ele.offset();

        var defaults = {
            trigger: '',
            weekStart: 1,
            yearRange: [-6, 6],
            format: 'yyyy-mm-dd',
            language: 'zh_CN'
        };
        $.extend(defaults, options);
        var namespace = 'datepicker';

        var languagePack = DatePicker.language[defaults.language];
        var EVENT_FOCUS = 'focus.' + namespace;
        var EVENT_CLICK = 'click.' + namespace;
        var EVENT_MOUSEDOWN = 'mousedown.' + namespace;

        var tpl = '<div class="{{namespace}}" style="top:{{positionTop}};left:{{positionLeft}}" >\
                    <div class="top">\
                        <div class="{{namespace}}-select {{namespace}}-select-year">\
                            <div class="{{namespace}}-select-selected"></div>\
                            <ul class="{{namespace}}-select-options">\
                            {{yearRange}}\
                            </ul>\
                        </div>\
                        <div class="{{namespace}}-select {{namespace}}-select-month">\
                            <div class="{{namespace}}-select-selected"></div>\
                                <ul class="{{namespace}}-select-options">\
                                    <li data-month="1">&ensp;1</li>\
                                    <li data-month="7">&ensp;7</li>\
                                    <li data-month="2">&ensp;2</li>\
                                    <li data-month="8">&ensp;8</li>\
                                    <li data-month="3">&ensp;3</li>\
                                    <li data-month="9">&ensp;9</li>\
                                    <li data-month="4">&ensp;4</li>\
                                    <li data-month="10">10</li>\
                                    <li data-month="5">&ensp;5</li>\
                                    <li data-month="11">11</li>\
                                    <li data-month="6">&ensp;6</li>\
                                    <li data-month="12">12</li>\
                                </ul>\
                            </div>\
                        </div>\
                    <table class="body">\
                        <thead>\
                            <tr>\
                                {{weekHead}}\
                            </tr>\
                        </thead>\
                        <tbody>\
                        </tbody>\
                    </table>\
                    <div class="bottom">\
                        <div class="btn-clear">{{clearText}}</div>\
                    </div>\
            </div>';

        var tplData = $.extend({}, {
            yearRange: function getYearRange() {
                var now = new Date();
                var startYear = now.getFullYear() + defaults.yearRange[0];
                var rangeSpan = defaults.yearRange[1] - defaults.yearRange[0];
                var rows = Math.ceil(rangeSpan / 2);
                var html = [];
                for (var i = 0; i < rows; i++) {
                    html.push('<li data-year="' + (startYear + i) + '">' + (startYear + i) + '</li>');
                    html.push('<li data-year="' + (startYear + i + rows) + '">' + (startYear + i + rows) + '</li>');
                }
                if (rangeSpan % 2 != 0) {
                    html.pop();
                }
                return html.join('');
            }(),
            weekHead: function getWeekHead() {
                var html = [];
                for (var i = defaults.weekStart; i < defaults.weekStart + 7; i++) {
                    html.push('<td class="cell week-cell">' + languagePack.week[i % 7] + '</td>');
                }
                return html.join('');
            }(),
            clearText: languagePack.clearText,
            positionTop: pos.top + ele.outerHeight() + 'px',
            positionLeft: pos.left + 'px',
            namespace: namespace
        });

        tpl = tpl.replace(/\{\{(\w+)\}\}/g, function (m, c) {
            return tplData[c];
        });


        var baseCls = '.' + namespace;
        var selectCls = baseCls + '-select';
        var selectOptionsCls = selectCls + '-options';
        var selectOptionCls = selectCls + '-options li';
        var selectSelectedCls = selectCls + '-selected';
        var selectYearCls = selectCls + '-year';
        var selectMonthCls = selectCls + '-month';

        var $datepicker = $(tpl).appendTo(document.body);
        var $selectedYear = $datepicker.find(selectYearCls + ' ' + selectSelectedCls);
        var $selectedMonth = $datepicker.find(selectMonthCls + ' ' + selectSelectedCls);
        var $dateArea = $datepicker.find('.body tbody');


        $datepicker.on(EVENT_CLICK, selectCls, function () {
            var options = $(this).find(selectOptionsCls);
            $(this).siblings(selectCls).find(selectOptionsCls).fadeOut(200);
            var selectedData = $(this).find(selectSelectedCls).data();
            if (options.is(':hidden')) {
                options.find('.selected').removeClass('selected');
                if (selectedData.year) {
                    options.find('[data-year=' + selectedData.year + ']').addClass('selected');
                } else {
                    options.find('[data-month=' + selectedData.month + ']').addClass('selected');
                }
                options.fadeIn(100);
            } else {
                options.fadeOut(200);
            }

        }).on(EVENT_CLICK, selectOptionCls, function () {
            // 点击选择年份
            var year = $(this).data('year') || $selectedYear.data('year');
            var month = $(this).data('month') || $selectedMonth.data('month');
            getDatesOfMonth(year, month);

        }).on(EVENT_CLICK, '.curr-month,.prev-month,.next-month', function () {
            // 鼠标移出年份，月份选择区域
            $dateArea.find('.selected').removeClass('selected');
            $(this).addClass('selected');
            var value = $(this).data('value');
            ele.val(value);
            $datepicker.hide();

        }).on(EVENT_CLICK, '.btn-clear', function () {
            ele.val('');
            $datepicker.hide();
        });

        if ($(defaults.trigger).length > 0) {
            $(defaults.trigger).on(EVENT_CLICK, function () {
                if ($datepicker.is(':hidden')) {
                    show();
                } else {
                    hide();
                }
            });
        } else {
            ele.on(EVENT_FOCUS, show);
        }

        $(document).on(EVENT_MOUSEDOWN, function (e) {
            var target = $(e.target);
            if (target.closest(defaults.trigger).length == 0 && target.closest('.datepicker').length == 0 && !target.is(ele)) {
                $datepicker.hide();
            }
        });

        function show() {
            var date = getValue();
            getDatesOfMonth(date.year, date.month);
            $datepicker.find(selectOptionsCls).hide();
            $datepicker.show();
        }

        function hide() {
            $datepicker.hide();
        }

        function getDatesOfMonth(year, month) {
            var dates = [];
            // 初始化为month第一天的日期
            var date = new Date(year, month - 1, 1);
            var dayOfWeek = date.getDay();

            var lastMonthDays = 0;
            if (dayOfWeek != defaults.weekStart) {
                date.setDate(0);  // 上月最后一天
                var prevDate = date.getDate();
                var lastMonthDays = dayOfWeek - defaults.weekStart;
                if (lastMonthDays < 0) {
                    lastMonthDays += 7;
                }
                // -1是因为i可以等于0
                for (var i = lastMonthDays - 1; i >= 0; i--) {
                    dates.push({
                        'value': formatDate(date.getFullYear(), date.getMonth() + 1, prevDate - i),
                        'date': prevDate - i,
                        'class': 'prev-month'
                    });
                }
            }
            date.setFullYear(year, month, 0);

            for (var i = 1, j = date.getDate(); i <= j; i++) {
                dates.push({
                    'value': formatDate(date.getFullYear(), date.getMonth() + 1, i),
                    'date': i,
                    'class': 'curr-month'
                });
            }

            // 对于$datepicker选中的日期要增加选中的样式
            var selectedDate = getValue();
            if (selectedDate.year == year && selectedDate.month == month) {
                // -1是数组下标从0开始
                dates[lastMonthDays + selectedDate.day - 1]['class'] += ' selected';
            }

            // 上月日期总数+当月日期总数之和不为7的倍数才会显示下月的部分日期
            if (dates.length % 7 > 0) {
                date.setFullYear(year, month, 1);
                for (var i = 1, j = 7 - dates.length % 7; i <= j; i++) {
                    dates.push({
                        'value': formatDate(date.getFullYear(), date.getMonth() + 1, i),
                        'date': i,
                        'class': 'next-month'
                    });
                }
            }
            $selectedYear.data('year', year).text(year + languagePack.yearText);
            $selectedMonth.data('month', month).text(month + languagePack.monthText);
            $dateArea.html(getDatesDom(dates));
        }

        function getDatesDom(dates) {
            var dom = [];
            dom.push('<tr>');
            for (var i = 0, j = dates.length; i < j; i++) {
                dom.push('<td class="cell ' + dates[i]['class'] + '" data-value="' + dates[i]['value'] + '">' + dates[i]['date'] + '</td>');
                if ((i + 1) % 7 == 0 && i != j - 1) {
                    dom.push('</tr></tr>');
                }
            }
            dom.push('</tr>');
            return dom.join('');
        }

        function formatDate(year, month, day) {
            return defaults.format.replace(/[ymd]+/gi, function (m) {
                m = m.toLowerCase();
                if (m == 'yyyy') {
                    return year;
                } else if (m == 'mm') {
                    return month < 10 ? '0' + month : month;
                } else {
                    return day < 10 ? '0' + day : day;
                }
            });
        }

        function getValue() {
            var date = {};
            var v = ele.val();
            var yearStartIndex = 0;
            var monthStartIndex = 0;
            var dayStartIndex = 0;
            var formatRegStr = defaults.format.replace(/[ymd]+|[^ymd]/gi, function (m, i) {
                m = m.toLowerCase();
                if (m == 'yyyy') {
                    yearStartIndex = i;
                    return '\\d{4}';
                } else if (m == 'mm') {
                    monthStartIndex = i;
                    return '\\d{2}';
                } else if (m == 'dd') {
                    dayStartIndex = i;
                    return '\\d{2}';
                } else {
                    return '\\' + m;
                }
            });
            var formatReg = new RegExp(formatRegStr);
            if (formatReg.test(v)) {
                date = {
                    year: v.substr(yearStartIndex, 4) - 0,
                    month: v.substr(monthStartIndex, 2) - 0,
                    day: v.substr(dayStartIndex, 2) - 0
                };
            } else {
                var now = new Date();
                date = {
                    year: now.getFullYear(),
                    month: now.getMonth() + 1,
                    day: now.getDate()
                };
            }
            return date;
        }

        return $datepicker;
    };
    DatePicker.language = {
        zh_CN: {
            yearText: '年',
            monthText: '月',
            clearText: '清除',
            week: ['日', '一', '二', '三', '四', '五', '六']
        }
    };

    $.fn.datepicker = DatePicker;
    $.fn.datepicker.language = DatePicker.language;

    return $;
});